//
//  UIView+Extension.swift
//  Library_y
//
//  Created by JC on 2023/6/6.
//

import Foundation
import UIKit

// view from xib
public extension UIView {
    static func nibView<T: UIView>(type: T.Type) -> T? {
        let nib: UINib = UINib(nibName: "\(type.self)", bundle: nil)
        let view = nib.instantiate(withOwner: nil, options: nil).first
        return view as? T
    }
}

protocol Nibloadable { }
extension Nibloadable where Self : UIView {
    static func loadNib(_ nibNmae :String? = nil) -> Self {
        return Bundle.main.loadNibNamed(nibNmae ?? "\(self)", owner: nil, options: nil)?.first as! Self
    }
}

public extension UIView {
    
    /// 动画缩放效果
    func scaleAnimate() {
        let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
        scaleAnimation.values = [1.0, 0.3, 1.5, 1.0]
        scaleAnimation.duration = 0.5
        layer.add(scaleAnimation, forKey: "scaleAnimation")
    }
}

public extension UIView {
    
    var aspectRatio: CGFloat {
        return bounds.width / bounds.height
    }
}

public extension UIView {
    
    convenience init(center: CGPoint, size: CGSize) {
        self.init(frame: CGRect(origin: .zero, size: size))
        self.center = center
    }
    
    convenience init(centerX x: CGFloat, centerY y: CGFloat, width: CGFloat, height: CGFloat) {
        self.init(center: CGPoint(x: x, y: y), size: CGSize(width: width, height: height))
    }
}

public extension UIView {
    
    /// 应用遮罩
    ///
    /// - parameter image: 遮罩图像
    /// - parameter color: 背景颜色
    func applyCover(with image: UIImage, color: UIColor) {
        let maskView = CALayer()
        maskView.frame = bounds
        maskView.contents = image.cgImage
        backgroundColor = color
        layer.mask = maskView
    }
    
    /// 更新遮罩尺寸
    func updateCoverSize() {
        layer.mask?.frame = bounds
    }
}

public extension UIView {
    
    // MARK: - 视图
    
    /// 初始化所有界面默认视图
    class func setupAllViewAppearance() {
        UITableView.appearance().tableFooterView = UIView()
        UIView.appearance().layer.isDoubleSided = false // 无效
    }
    
    /// 截图
    ///
    /// - returns: 图片
    func shot() -> UIImage? {
        
        UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
        drawHierarchy(in: bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
        
        //        guard let content = UIGraphicsGetCurrentContext() else { return nil }
        //        UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
        //        layer.render(in: content)
        //        let image = UIGraphicsGetImageFromCurrentImageContext()
        //        UIGraphicsEndImageContext()
        //        return image
    }
    
    /// 添加圆角
    ///
    /// - parameter cornerRadius: 圆角弧度
    func setCornerRadius(cornerRadius: CGFloat, _ roundingCorners:UIRectCorner) {
        
        let path = UIBezierPath(roundedRect: self.bounds,
                                byRoundingCorners: roundingCorners,
                                cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
        let layer = CAShapeLayer()
        layer.frame = self.bounds
        layer.path = path.cgPath
        self.layer.mask = layer
        layer.shouldRasterize = true
        layer.rasterizationScale = UIScreen.main.scale
    }
    
    /**
     * 切圆角
     * - Parameters:
     *  - conrners
     *  - radius 圆角弧度
     */
    func addCorner(conrners: UIRectCorner , radius: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: conrners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer.init()
        maskLayer.frame = self.bounds
        maskLayer.path = maskPath.cgPath
        self.layer.mask = maskLayer
    }
    
    
    // MARK: - 布局
    
    /// 将内部所有 subview 进行水平布局
    ///
    /// - parameter padding: subview 间的距离
    /// - parameter inset:   subview 与 superview 的内距
    func horizontalLayout(withPadding padding: CGFloat = 0, inset: UIEdgeInsets = UIEdgeInsets.zero) {
        
        self.removeConstraints(self.constraints)
        
        let subviews = self.subviews.filter { (view) -> Bool in
            return !view.isHidden && view.alpha != 0
        }
        
        guard subviews.count > 0 else { return }
        
        var viewDictionary = [String: UIView]()
        var hVlfs = "H:|-\(inset.left)-"
        
        for (idx, subview) in subviews.enumerated() {
            
            subview.translatesAutoresizingMaskIntoConstraints = false
            
            if idx == 0 {
                hVlfs.append("[v\(idx)]-\(padding)")
            } else if idx == (subviews.count - 1) {
                hVlfs.append("-[v\(idx)(==v0)]")
            } else {
                hVlfs.append("-[v\(idx)(==v0)]-\(padding)")
            }
            
            viewDictionary["v\(idx)"] = subview
            
            let vVlf = "V:|-\(inset.top)-[v\(idx)]-\(inset.bottom)-|"
            let vLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: vVlf, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
            self.addConstraints(vLayoutConstraints)
        }
        hVlfs.append("-\(inset.right)-|")
        
        let hLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: hVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
        self.addConstraints(hLayoutConstraints)
    }
    
    /// 将内部所有 subview 进行垂直布局
    ///
    /// - parameter padding: subview 间的距离
    /// - parameter inset:   subview 与 superview 的内距
    func verticalLayout(withPadding padding: CGFloat = 0, inset: UIEdgeInsets = UIEdgeInsets.zero) {
        
        self.removeConstraints(self.constraints)
        
        let subviews = self.subviews.filter { (view) -> Bool in
            return !view.isHidden && view.alpha != 0
        }
        
        guard subviews.count > 0 else { return }
        
        var viewDictionary = [String: UIView]()
        var vVlfs = "V:|-\(inset.top)-"
        
        for (idx, subview) in subviews.enumerated() {
            
            subview.translatesAutoresizingMaskIntoConstraints = false
            
            if idx == 0 {
                vVlfs.append("[v\(idx)]-\(padding)")
            } else if idx == (subviews.count - 1) {
                vVlfs.append("[v\(idx)(==v0)]")
            } else {
                vVlfs.append("[v\(idx)(==v0)]-\(padding)")
            }
            
            viewDictionary["v\(idx)"] = subview
            
            let hVlf = "H:|-\(inset.left)-[v\(idx)]-\(inset.right)-|"
            let hLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: hVlf, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
            self.addConstraints(hLayoutConstraints)
        }
        vVlfs.append("-\(inset.bottom)-|")
        
        let vLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: vVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
        self.addConstraints(vLayoutConstraints)
    }
    
    /// 将内部所有 subview 进行格子布局
    ///
    /// - parameter column:  行数
    /// - parameter minSize: subview 的最小尺寸
    /// - parameter padding: subview 间的距离
    /// - parameter inset:   subview 与 superview 的内距
    // swiftlint:disable cyclomatic_complexity
    func gridLayout(withColumn column: Int, minSize: CGSize, padding: CGFloat = 0, inset: UIEdgeInsets = UIEdgeInsets.zero) {
        
        // 移除之前的约束
        self.removeConstraints(self.constraints)
        
        // 获取显示出来的子窗口
        let layoutViews = self.subviews.filter { (subview) -> Bool in
            return !subview.isHidden && (subview.alpha != 0)
        }
        
        // 计算总共有几行
        var row = layoutViews.count / column
        row += ((layoutViews.count % column == 0) ? 0 : 1)
        
        var horizontalPadding = padding
        var verticalPadding = padding
        let horizontalInset = inset.left + inset.right
        let verticalInset = inset.top + inset.bottom
        var fitInset = inset
        
        // 计算子窗口的宽度和高度
        var itemWidth = (self.bounds.width - (padding * CGFloat(column - 1)) - horizontalInset) / CGFloat(column)
        var itemHeight = (self.bounds.height - (padding * CGFloat(row - 1)) - verticalInset) / CGFloat(row)
        
        if itemWidth < minSize.width {
            
            // 如果子窗口的宽度小于规定的最小宽度,则重新计算满足最小宽度所需要的水平 padding 值
            horizontalPadding = (self.bounds.width - horizontalInset - minSize.width * CGFloat(column)) / CGFloat(column - 1)
            
            // 如果重新计算得到的 padding 值小于 0，并且可以用 inset 进行弥补，则重新计算满足目标布局的最小 inset 和 padding
            if horizontalPadding < 0 {
                
                guard -horizontalPadding < horizontalInset else { abort() }
                
                horizontalPadding = (horizontalInset + horizontalPadding) / CGFloat(2 + column - 1)
                fitInset.left = horizontalPadding
                fitInset.right = horizontalPadding
            }
            
            // 子窗口设为最小宽度
            itemWidth = minSize.width
        }
        
        if itemHeight < minSize.height {
            
            // 如果子窗口的高度小于规定的最小高度,则重新计算满足最小高度所需要的垂直 padding 值
            verticalPadding = (self.bounds.height - verticalInset - minSize.height * CGFloat(row)) / CGFloat(row - 1)
            
            // 如果重新计算得到的 padding 值小于 0，并且可以用 inset 进行弥补，则重新计算满足目标布局的最小 inset 和 padding
            if verticalPadding < 0 {
                
                guard -verticalPadding < verticalInset else { abort() }
                
                verticalPadding = (verticalInset + verticalPadding) / CGFloat(2 + row - 1)
                fitInset.top = verticalPadding
                fitInset.bottom = verticalPadding
            }
            
            // 子窗口设为最小高度
            itemHeight = minSize.height
        }
        
        var viewDictionary = [String: UIView]()
        
        var hVlfs = "H:|-\(fitInset.left)-"
        
        for (idx, subview) in layoutViews.enumerated() {
            
            subview.translatesAutoresizingMaskIntoConstraints = false
            
            viewDictionary["v\(idx)"] = subview
            
            let columnIdx = idx % column
            
            if columnIdx == 0 {
                if idx == 0 {
                    hVlfs = "H:|-\(fitInset.left)-[v\(idx)]-"
                } else {
                    hVlfs = "H:|-\(fitInset.left)-[v\(idx)(==v0)]-"
                }
            } else {
                hVlfs.append("\(horizontalPadding)-[v\(idx)(==v0)]-")
            }
            
            if columnIdx == column - 1 {
                
                hVlfs.append("\(fitInset.right)-|")
                Log_y.print_("hVlfs = \(hVlfs)")
                let hLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: hVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
                self.addConstraints(hLayoutConstraints)
                
            } else if idx == layoutViews.count - 1 {
                
                let str = NSString(string: hVlfs)
                hVlfs = str.substring(to: str.length - 1)
                Log_y.print_("hVlfs = \(hVlfs)")
                let hLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: hVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
                self.addConstraints(hLayoutConstraints)
                
            }
        }
        
        var vVlfs = "V:|-\(fitInset.top)-"
        
        for columnIdx in 0..<column {
            
            for rowIdx in 0..<row {
                
                let viewIdx = rowIdx * column + columnIdx
                
                if viewIdx >= layoutViews.count {
                    let str = NSString(string: vVlfs)
                    vVlfs = str.substring(to: str.length - 1)
                    Log_y.print_("vVlfs = \(vVlfs)")
                    let vLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: vVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
                    self.addConstraints(vLayoutConstraints)
                    break
                }
                
                if viewIdx == columnIdx {
                    if columnIdx == 0 {
                        vVlfs = "V:|-\(fitInset.top)-[v\(viewIdx)]-"
                    } else {
                        vVlfs = "V:|-\(fitInset.top)-[v\(viewIdx)(==v0)]-"
                    }
                } else {
                    vVlfs.append("\(verticalPadding)-[v\(viewIdx)(==v0)]-")
                }
                
                if rowIdx == row - 1 {
                    vVlfs.append("\(fitInset.bottom)-|")
                    Log_y.print_("vVlfs = \(vVlfs)")
                    let vLayoutConstraints = NSLayoutConstraint.constraints(withVisualFormat: vVlfs, options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: nil, views: viewDictionary)
                    self.addConstraints(vLayoutConstraints)
                }
            }
        }
    }
}

extension UIView {
    
    // 设置阴影
    public func shadow_set_page(_ cornerRadius: CGFloat = 12) {
        layer.cornerRadius = cornerRadius
        layer.shadowColor = UIColor(hex: "#1B518F").cgColor
        layer.shadowOpacity = 0.3
        // 设置阴影所照射的范围
        layer.shadowRadius = 5
        layer.shadowOffset = CGSize(width: 3, height: 3)
        layer.masksToBounds = false
    }
    
    // 设置通用阴影
    public func shadow_set(_ cornerRadius: CGFloat = 8, _ shadowColor: UIColor = UIColor(hex: "#181D30")) {
        layer.cornerRadius = cornerRadius
        layer.shadowColor = shadowColor.cgColor
        layer.shadowOpacity = 0.15
        // 设置阴影所照射的范围
        layer.shadowRadius = 3
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.masksToBounds = false
    }
    
    // 设置线阴影
    public func shadow_line(_ shadowOffsetHeight: CGFloat = 2) {
        layer.shadowColor = UIColor(hex: "#000000").cgColor
        layer.shadowOpacity = 0.2
        // 设置阴影所照射的范围
        layer.shadowRadius = 2
        layer.shadowOffset = CGSize(width: 0, height: shadowOffsetHeight)
        layer.masksToBounds = false
    }
    
    // 设置通用圆角虚线
    public func dottedLineView(_ radii: CGFloat = 8) {
        let size = CGSize(width: radii, height: radii)
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: size)
        let border = CAShapeLayer()
        border.strokeColor = Color.hex_3.cgColor
        border.masksToBounds = true
        border.fillColor = nil
        border.path = path.cgPath
        border.frame = bounds
        border.lineWidth = 1
//        border.lineCap = .square
        border.lineDashPattern = [3, 3]
        layer.addSublayer(border)
    }
    
    // 设置虚线
    func dottedLine() {
        let height = bounds.height
        let width = bounds.width
        let imgV = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
        addSubview(imgV)
        UIGraphicsBeginImageContext(imgV.frame.size)
        let context = UIGraphicsGetCurrentContext()
        context?.setLineCap(CGLineCap.square)
        let lengths: [CGFloat] = [4,2]
        context?.setStrokeColor(Color.hex_3.cgColor)
        context?.setLineWidth(1)
        context?.setLineDash(phase: 0, lengths: lengths)
        context?.move(to: CGPoint(x: 0, y: height))
        context?.addLine(to: CGPoint(x: width, y: height))
        context?.strokePath()
        imgV.image = UIGraphicsGetImageFromCurrentImageContext()
        // 结束
        UIGraphicsEndImageContext()
    }
}

// 逐渐透明的方向
public enum AlphaDirection {
    case topToDown
    case downToTop
}

extension UIView {
    
    /// 设置逐渐的透明遮盖
    public func setGraduallyAlpha(_ direction: AlphaDirection = .topToDown) {
        let gradLayer = CAGradientLayer()
        gradLayer.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height)
        var colors: [CGColor] = []
        for i in 0..<10 {
            colors.append(UIColor.init(white: 1, alpha: CGFloat(direction == .topToDown ? (10 - i) : i)/10.0).cgColor)
        }
        gradLayer.colors = colors
        layer.mask = gradLayer
    }
    
    /// 设置相册封面的的透明遮盖
    public func setAlbumCoverAlpha(w: CGFloat, h: CGFloat) {
        backgroundColor = .black
        let mask = CAGradientLayer()
        mask.startPoint = CGPoint(x: 0, y: 0)
        mask.endPoint = CGPoint(x: 0, y: 1)
        mask.colors = [UIColor.black.withAlphaComponent(0.0).cgColor,
                       UIColor.black.withAlphaComponent(0.2),
                       UIColor.black.withAlphaComponent(0.4).cgColor]
        mask.locations = [NSNumber(value: 0.0), NSNumber(value: 0.0), NSNumber(value: 1.0)]
        mask.frame = CGRect(x: 0, y: 0, width: w, height: h)
        layer.mask = mask
    }
    
    /// 设置相册视频列表顶部的透明遮盖
    public func setPhotoVideoListTopCoverAlpha(w: CGFloat, h: CGFloat) {
        backgroundColor = .black
        let mask = CAGradientLayer()
        mask.startPoint = CGPoint(x: 0, y: 1)
        mask.endPoint = CGPoint(x: 0, y: 0)
        mask.colors = [UIColor(hex: "#F5F5F5").withAlphaComponent(0.4).cgColor,
                       UIColor.black.withAlphaComponent(0.5),
                       UIColor.black.withAlphaComponent(0.6).cgColor]
        mask.locations = [NSNumber(value: 0.0), NSNumber(value: 0.0), NSNumber(value: 1.0)]
        mask.frame = CGRect(x: 0, y: 0, width: w, height: h)
        layer.mask = mask
    }
    
    /// 设置相册列表中 年/月 相册集封面
    public func setPhotoVideoListDateCoverAlpha(w: CGFloat, h: CGFloat) {
        backgroundColor = .black
        let mask = CAGradientLayer()
        mask.startPoint = CGPoint(x: 0, y: 1)
        mask.endPoint = CGPoint(x: 0, y: 0)
        mask.colors = [UIColor(hex: "#000000").withAlphaComponent(0.5).cgColor,
                       UIColor(hex: "#848484").withAlphaComponent(0.5),
                       UIColor.white.withAlphaComponent(0.1).cgColor]
        mask.locations = [NSNumber(value: 0.0), NSNumber(value: 0.0), NSNumber(value: 1.0)]
        mask.frame = CGRect(x: 0, y: 0, width: w, height: h)
        layer.mask = mask
    }
}

/// 点击事件可以穿透的View
public class PassThroughView: UIView {
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, with: event)
        return hitView == self ? nil : hitView
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

/// 点击事件可以穿透的View
public class PassThroughXibView: UIView {
    
    public override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let hitView = super.hitTest(point, with: event)
        return hitView == self ? nil : hitView
    }
}
